package org.springframework.boot.netty.argumentResolver;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.netty.annotation.ResponseBody;
import org.springframework.boot.netty.listener.Message;
import org.springframework.boot.netty.support.JsonUtil;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Method;
import java.nio.charset.Charset;


/**
 * Author: huoxingzhi
 * Date: 2020/12/22
 * Email: hxz_798561819@163.com
 */
public class ResponseBodyReturnValueArgumentResolver extends ReturnValueArgumentResolverAdapter {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        Method method = methodParameter.getMethod();
        ResponseBody annotation = AnnotationUtils.findAnnotation(method, ResponseBody.class);
        return !ObjectUtils.isEmpty(annotation);
    }

    @Override
    public void resolveArgument(Message message, Object returnValue, MethodParameter methodParameter) throws Exception {
        Method method = methodParameter.getMethod();
        ResponseBody annotation = AnnotationUtils.findAnnotation(method, ResponseBody.class);
        Channel currentChannel = message.getCurrentChannel();
        FullHttpResponse response;
        try {
            // http协议传输json格式数据，将返回值json格式化
            String retuenJson = JsonUtil.obj2StringPretty(returnValue);
            ByteBuf buf = copiedBuffer(retuenJson, CharsetUtil.UTF_8);
            // 设置http响应头，并返回给客户端
            response = responseOk(HttpResponseStatus.OK,buf);
        }catch (Exception e){
            response = responseOk(HttpResponseStatus.INTERNAL_SERVER_ERROR,null);
        }

        if(annotation.enableAccessControlAllow()){
            //允许跨域访问
            response.headers()
                    .set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN,
                            StringUtils.join(annotation.accessControlAllowOrigin(),","));
            response.headers()
                    .set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_HEADERS,
                            StringUtils.join(annotation.accessControlAllowHeaders(),","));
            response.headers()
                    .set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_METHODS,
                            StringUtils.join(annotation.accessControlAllowMethods(),","));
        }


        // 发送响应，成功后关闭channel
        currentChannel.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);

    }

    private ByteBuf copiedBuffer(String data, Charset utf8) {
        return Unpooled.wrappedBuffer(data.getBytes());
    }


    private FullHttpResponse responseOk(HttpResponseStatus status, ByteBuf buf) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                status,buf);
        if(buf != null){
            response.headers().set("Content-Type","application/json;charset=UTF-8");
            response.headers().set("Content-Length",response.content().readableBytes());
        }
        return response;
    }

}
